const net = require('net');   // 提供 TCP 操作，原生 socket 是基于这个库，对这个库二次封装
const crypto = require('crypto');   // 校验

let server = net.createServer(sock => {
	// 现在前台的 Status 处于pending的状态,需要后面返回给客户端一个状态
	// 有数据请求，once 事件只执行一次
	sock.once('data', data => {   // 这里是二进制数据，肯定是字符串
		console.log('握手开始');
		let str = data.toString();
		/**  console.log(str)  原始数据
		GET / HTTP/1.1
		Host: localhost:8080
		Connection: Upgrade     // 这是一个升级协议
		Pragma: no-cache
		Cache-Control: no-cache
		Upgrade: websocket    // 要升级为 websocket
		Origin: file://
		Sec-WebSocket-Version: 13    // websocket版本
		User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1
		Accept-Encoding: gzip, deflate, br
		Accept-Language: zh-CN,zh;q=0.9
		Sec-WebSocket-Key: u4fKa67U4v4eghznfKxoHg==      // 密钥
		Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
		*/
		// 1. 删除第一行
		let lines = str.split('\r\n');
		lines = lines.slice(1, lines.length - 2);
		// 2. 用': '切割每行数据
		let headers = {};
		lines.forEach(line => {
			let [key, val] = line.split(': ');
			headers[key.toLowerCase()] = val;
		})

		if (headers['upgrade'] != 'websocket') {
			console.log('其他协议', headers['upgrade'])
			sock.end();
		} else if (headers['sec-websocket-version'] != 13) {
			console.log('版本不对', headers['sec-websocket-version']);
			sock.end();
		} else {
			// mask：258EAFA5-E914-47DA-95CA-C5AB0DC85B11
			// 这里需要将key 和 mask拼接到一起
			let key = headers['sec-websocket-key'];
			let mask = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
			let hash = crypto.createHash('sha1');
			hash.update(key + mask);
			// key2 需要返回给客户端
			let key2 = hash.digest('base64');
			// 101 是正在切换协议，也就是协议升级
			sock.write(`HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ${key2}\r\n\r\n`);
			// 这次握手结束，Status会脱离pending的状态，变为101，前台的Time还是pending，这是正常的，因为websocket本来就是一直连接的
			console.log('握手结束');

			// 从这里开始握手结束，开始真正的处理数据
			sock.on('data', data => {
				console.log('有数据了');
				console.log(data);
				// 这里接收前台的数据不能直接使用，因为接收到的是二进制数据。也不能将其看作字符串，data实际上数据帧(数据包/数据报/数据块)。
				// 也就是说这个data是一个结构化(帧结构)的数据，不是非结构化(字符串就是非结构化数据)。结构化数据都有位这个概念。
				/**
				 * 1位(bit)，
				 * 8位(8bit) => 1字节(1byte)
				 * 
				 */
			})
		}
	})
	
	// 断开
	sock.on('end', () => {})
})

server.listen(8080);

